package xcmg.device.service.sale;

import com.github.pagehelper.PageInfo;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.CellType;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import xcmg.device.dao.entity.company.CompanyInfoDO;
import xcmg.device.dao.entity.delivery.DeliveryNoteDO;
import xcmg.device.dao.entity.delivery.DeliveryNoteDetailDO;
import xcmg.device.dao.entity.sale.SaleIntentionDetailDO;
import xcmg.device.dao.entity.salesReturn.SalesReturnApplyDO;
import xcmg.device.dao.entity.salesReturn.SalesReturnApplyDetailDO;
import xcmg.device.dao.entity.salesReturn.SalesReturnInDO;
import xcmg.device.dao.mapper.CompanyInfoMapper;
import xcmg.device.dao.mapper.SaleIntentionDetailMapper;
import xcmg.device.dao.mapper.SaleIntentionMapper;
import xcmg.device.dao.mapper.delivery.DeliveryNoteDetailMapper;
import xcmg.device.dao.mapper.delivery.DeliveryNoteMapper;
import xcmg.device.dao.mapper.salesReturn.ReturnApplyDetailMapper;
import xcmg.device.dao.mapper.salesReturn.ReturnApplyMapper;
import xcmg.device.dao.mapper.salesReturn.ReturnInMapper;
import xcmg.device.infra.DateUtil;
import xcmg.device.infra.ErrorCode;
import xcmg.device.infra.ExportUtil;
import xcmg.device.infra.FileUtil;
import xcmg.device.infra.ImportUtil;
import xcmg.device.infra.SalesReturnConstants;
import xcmg.device.infra.enums.BillDesc;
import xcmg.device.service.GenDocumentService;
import xcmg.device.service.basic.MaterialsService;
import xcmg.device.service.delivery.DeliveryNoteService;
import xcmg.device.service.marketing.MarketingActivityService;
import xcmg.device.service.vo.FunctionResult;
import xcmg.device.service.vo.basic.MaterialsVO;
import xcmg.device.service.vo.delivery.DeliveryNoteVO;
import xcmg.device.service.vo.sale.SaleAddVO;
import xcmg.device.service.vo.sale.SaleIntentionDetailVO;
import xcmg.device.service.vo.sale.SaleIntentionVO;
import xcmg.device.service.vo.salesReturn.SalesReturnApplyAddVO;
import xcmg.device.service.vo.salesReturn.SalesReturnApplyDetailVO;
import xcmg.device.service.vo.salesReturn.SalesReturnApplyExportVO;
import xcmg.device.service.vo.salesReturn.SalesReturnApplyVO;
import xcmg.device.service.vo.salesReturn.SalesReturnAuditVO;
import xcmg.device.service.warehouse.WarehouseDeliveryService;
import xcmg.device.service.warehouse.WarehouseInboundService;
import yb.ecp.fast.feign.FastGenClient;
import yb.ecp.fast.infra.infra.ActionResult;
import yb.ecp.fast.infra.infra.PageCommonVO;
import yb.ecp.fast.infra.infra.SearchCommonVO;
import yb.ecp.fast.infra.util.ListUtil;
import yb.ecp.fast.infra.util.PageHelperPlus;
import yb.ecp.fast.infra.util.Ref;
import yb.ecp.fast.infra.util.StringUtil;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


/**
 * Created by LiChangjiang on 2018/3/6 0006.
 */
@Service
public class ReturnApplyService
{
    @Autowired
    private ReturnApplyMapper returnApplyMapper;

    @Autowired
    private ReturnApplyDetailService returnApplyDetailService;

    @Autowired
    private ReturnApplyDetailMapper returnApplyDetailMapper;

    @Autowired
    private WarehouseDeliveryService warehouseDeliveryService;

    @Autowired
    private ReturnInMapper returnInMapper;

    @Autowired
    private SaleIntentionMapper saleIntentionMapper;

    @Autowired
    private GenDocumentService genDocumentService;

    @Autowired
    private SaleIntentionDetailMapper saleIntentionDetailMapper;

    @Autowired
    private SaleIntentionService saleIntentionService;

    @Autowired
    private DeliveryNoteMapper deliveryNoteMapper;

    @Autowired
    private DeliveryNoteDetailMapper deliveryNoteDetailMapper;

    @Autowired
    private DeliveryNoteService deliveryNoteService;

    @Autowired
    private WarehouseInboundService warehouseInboundService;

    @Autowired
    private HttpServletResponse response;

    @Autowired
    private FastGenClient fastGenClient;

    @Autowired
    private CompanyInfoMapper companyInfoMapper;

    @Autowired
    private MaterialsService materialsService;

    @Autowired
    private MarketingActivityService marketingActivityService;

    @Value("${spring.file.download.path}")
    private String filePath;

    private String templateExcelFileName="SalesReturnApply.xls";

    /**
     * 查询退货申请列表
     *
     * @param condition SearchCommonVO<SalesReturnApplyVO>
     * @return PageCommonVO
     */
    public PageCommonVO list(SearchCommonVO<SalesReturnApplyVO> condition)
    {
        PageCommonVO<SalesReturnApplyVO> result = new PageCommonVO<>();
        List<SalesReturnApplyVO> voList = new ArrayList<>();
        PageHelperPlus.startPage(condition.getPageNum(), condition.getPageSize(), "CREATE_DATE DESC");

        List<SalesReturnApplyDO> doList = returnApplyMapper.list(condition.getFilters());
        for (SalesReturnApplyDO entity : doList)
        {
            voList.add(getVO(entity));
        }
        result.setPageInfo(new PageInfo(doList));
        result.setPageInfoList(voList);
        return result;
    }

    /**
     * 查询退货申请详细信息
     *
     * @param id String
     * @return SalesReturnApplyVO
     * @throws Exception 
     */
    public SalesReturnApplyVO item(String id) throws Exception
    {
        SalesReturnApplyDO salesReturnApplyDO = returnApplyMapper.item(id);

        if (null == salesReturnApplyDO)
        {
            return null;
        }
        SalesReturnApplyVO salesReturnApplyVO = getVO(salesReturnApplyDO);

        List<SalesReturnApplyDetailVO> salesReturnApplyDetailVOs = returnApplyDetailService.list(id, salesReturnApplyDO);

        salesReturnApplyVO.setReturnApplyDetailVOs(salesReturnApplyDetailVOs);

        return salesReturnApplyVO;
    }

    /**
     * 删除锐或·退货申请记录
     *
     * @param ids List
     * @return ErrorCode
     */
    @Transactional(rollbackFor = Exception.class)
    public ErrorCode remove(List<String> ids) throws Exception
    {
        if (checkConditionBeforeRemove(ids))
        {
            return ErrorCode.CannotRemoveAudited;
        }
        for (String appId : ids)
        {
            //销售意向单状态为未退货
            updateByRemove(appId);
            returnApplyMapper.remove(appId);
            returnApplyDetailMapper.deleteByApply(appId);
        }
        return ErrorCode.Success;
    }

    /**
     * 删除退货申请单完成之后，修改销售意向单状态为“未申请”状态
     *
     * @param applyId String
     * @return ErrorCode
     */
    private ErrorCode updateAfterRemove(String applyId)
    {
        SalesReturnApplyDO applyDO = returnApplyMapper.item(applyId);
        saleIntentionMapper.updateApplyReturnStatus(applyDO.getSaleNo(), SalesReturnConstants.APPLY_NOT);
        return ErrorCode.Success;
    }

    /**
     * 退货申请删除或审核拒绝，还原销售单中的退货申请数量
     * @param applyId String
     * @throws Exception 
     */
    private void updateByRemove(String applyId) throws Exception
    {
        SalesReturnApplyVO applyVO = item(applyId);
        if(StringUtil.isNullOrEmpty(applyVO.getSaleNo())){
            return;
        }
        List<SalesReturnApplyDetailVO> detailVOList = applyVO.getReturnApplyDetailVOs();

        for (SalesReturnApplyDetailVO detailVO : detailVOList)
        {
            SaleIntentionDetailDO saleDetail = saleIntentionDetailMapper.selectByNo(applyVO.getSaleNo(), detailVO.getMaterialsNo());

            int returnFlag = 0; //退货状态（0未退货申请，1部分退货申请）
            //判断该零件删除后的状态是“部分退货申请”还是“为退货申请”
            if (detailVO.getApplyQty().compareTo(saleDetail.getAmountAfterAdjust()) != 0)
            {
                returnFlag = 1;
            }
            saleIntentionDetailMapper.updateByAutidFail(detailVO.getApplyQty(), applyVO.getSaleNo(), detailVO.getMaterialsNo(), returnFlag);
        }

        saleIntentionService.refreshSaleBillReturnStatus(applyVO.getSaleNo());
    }


    /**
     * 删除步骤校验，如果审核状态不是待审核状态（审核拒绝、审核通过），则不可以删除 ,返回TRUE
     *
     * @param ids List<String>
     * @return boolean
     */
    private boolean checkConditionBeforeRemove(List<String> ids)
    {
        for (String id : ids)
        {
            SalesReturnApplyDO salesReturnInDO = returnApplyMapper.item(id);
            if (null == salesReturnInDO)
            {
                continue;
            }
            if (4 == salesReturnInDO.getStatus())
            {
                return true;
            }
        }
        return false;
    }


    /**
     * 审核通过，更改销售意向单和发货通知单状态<br>
     * 1.查询销售意向单、发货通知单，如果未生成发货通知单，直接更改销售意向单状态为“退货完成”状态<br>
     * 2.如果已经生产发货通知单，发货通知单未出库，更改销售意向单和发货通知单状态为“退货完成“状态<br>
     * 3.如果发货通知单为出库状态，则更改销售意向单、发货通知单为“退货中”状态，添加退货信息，可以生成退货入库单<br>
     *
     * @param salesReturnApplyVO SalesReturnApplyVO
     * @return ErrorCode ErrorCode
     */
    @Transactional(rollbackFor = Exception.class)
    public ErrorCode auditPass(SalesReturnApplyVO salesReturnApplyVO) throws Exception
    {
        SalesReturnApplyDO salesReturnApplyDO = new SalesReturnApplyDO();
        String saleNo = salesReturnApplyVO.getSaleNo();
        String applyId = salesReturnApplyVO.getId();

        //1.获取销售意向单
        SaleAddVO saleAddVO = saleIntentionService.selectByNo(saleNo);
        if (null == saleAddVO)
        {
            return ErrorCode.Success;
        }

        updateApplyInfo(salesReturnApplyVO);

        saleIntentionMapper.updateApplyReturnStatus(saleNo, SalesReturnConstants.APPLY_PASS);

        /**销售意向单未发货*/
        if ("0".equals(saleAddVO.getHeaderInfo().getInventoryOutStatus()))
        {
            //2.销售意向单未发货，则变更销售意向单状态为退货完成
            ErrorCode errorCode = saleIntentionReturnDone(salesReturnApplyVO);
            if (ErrorCode.Success != errorCode)
            {
                return errorCode;
            }
            return ErrorCode.Success;
        }
        else
        {
            DeliveryNoteVO deliveryNoteVO = new DeliveryNoteVO();
            deliveryNoteVO.setSaleNo(saleNo);

            //查询销售意向单对应的所有发货通知单
            List<DeliveryNoteDO> deliveryNoteDOs = deliveryNoteMapper.list(deliveryNoteVO);

            if (ListUtil.isNullOrEmpty(deliveryNoteDOs))
            {
                //发货通知单数据获取失败，更改“发货通知单”“销售意向单”“退货申请单”状态为“退货完成”，“退货申请单”为“审核通过”状态
                ErrorCode errorCode = saleIntentionReturnDone(salesReturnApplyVO);
                if (ErrorCode.Success != errorCode)
                {
                    return errorCode;
                }
                return ErrorCode.Success;
            }

            //变更发货单状态为退货完成
            ErrorCode errorCode = deliveryNoteReturnDone(saleNo);
            if (ErrorCode.Success != errorCode)
            {
                return errorCode;
            }
            //获取可退货的零件信息
            List<SalesReturnApplyDetailDO> salesReturnApplyDetailDOList = getMaterrialsList(deliveryNoteDOs, applyId);

            if (ListUtil.isNullOrEmpty(salesReturnApplyDetailDOList))
            {
                //发货通知单零件数据没有出库状态数据，更改“发货通知单”“销售意向单”“退货申请单”状态为“退货完成”，“退货申请单”为“审核通过”状态
                ErrorCode eCode = saleIntentionReturnDone(salesReturnApplyVO);
                if (ErrorCode.Success != eCode)
                {
                    throw new Exception("添加退货申请，修改销售意向单状态异常！");
                }
                return ErrorCode.Success;
            }

            //替换退货申请中的零件信息，用发货通知单中已出库的零件信息
            ErrorCode addDetailCode = addApplyDetail(salesReturnApplyDetailDOList, applyId);

            if (ErrorCode.Success != addDetailCode)
            {
                return addDetailCode;
            }

            //退货中状态
            ErrorCode updateCode = saleIntentionReturnDoing(salesReturnApplyVO);
            if (ErrorCode.Success != updateCode)
            {
                return updateCode;
            }

            //修改发货单对应的事务单状态为“退货”
            warehouseDeliveryService.updateReturnStatus(deliveryNoteDOs, 1);


            return ErrorCode.Success;
        }
    }

    /**
     * 根据发货通知单信息获取可以退货入库的零件集合<br>
     * 如果发货通知单的零件状态为出库状态，则记录下该零件信息
     *
     * @param deliveryNoteDOs List<DeliveryNoteDO>
     * @param applyId         String
     * @return List<SalesReturnApplyDetailDO>
     */
    private List<SalesReturnApplyDetailDO> getMaterrialsList(List<DeliveryNoteDO> deliveryNoteDOs, String applyId)
    {
        List<SalesReturnApplyDetailDO> salesReturnApplyDetailDOs = new ArrayList<>();

        //遍历发货通知单对应的零件状态，如果为出库状态，则记录下来
        for (DeliveryNoteDO deliveryNoteDO : deliveryNoteDOs)
        {
            if ("0".equals(deliveryNoteDO.getIsOut()))
            {
                //未出库
                continue;
            }
            //2.发货单对应的零件信息为出库状态，则变更发货单以及零件状态为退货中状态
            List<DeliveryNoteDetailDO> deliveryNoteDetailDOList = deliveryNoteDetailMapper.list(deliveryNoteDO.getId());
            for (DeliveryNoteDetailDO deliveryNoteDetailDO : deliveryNoteDetailDOList)
            {
                if (deliveryNoteDetailDO.getInventoryOutAmount().compareTo(BigDecimal.ZERO) == 0)
                {
                    continue;
                }

                SalesReturnApplyDetailDO salesReturnApplyDetailDO = new SalesReturnApplyDetailDO();
                salesReturnApplyDetailDO.setApplyId(applyId);
                salesReturnApplyDetailDO.setSaleNo(deliveryNoteDO.getSaleNo());
                salesReturnApplyDetailDO.setDeliveryNo(deliveryNoteDetailDO.getDeliveryNoteNo());
                salesReturnApplyDetailDO.setMaterialsNo(deliveryNoteDetailDO.getMaterialsNo());
                salesReturnApplyDetailDO.setMaterialsDes(deliveryNoteDetailDO.getMaterialsDes());
                salesReturnApplyDetailDO.setUnit(deliveryNoteDetailDO.getUnit());
                salesReturnApplyDetailDO.setApplyQty(deliveryNoteDetailDO.getInventoryOutAmount());//最大退货数量为出库数量
                salesReturnApplyDetailDO.setDeliveryDetailId(deliveryNoteDetailDO.getId());
                salesReturnApplyDetailDO.setQty(deliveryNoteDetailDO.getQty());//采购数量为原数量

                salesReturnApplyDetailDOs.add(salesReturnApplyDetailDO);
            }
        }
        return salesReturnApplyDetailDOs;
    }

    /**
     * 根据销售意向单信息添加退货申请单信息
     *
     * @param saleAddVO SaleAddVO
     * @param applyId   String
     * @return ErrorCode
     * @throws Exception Exception
     */
    private ActionResult addBySaleIntention(SaleAddVO saleAddVO, String applyId, String remark, String deptName, String userId, String userName) throws Exception {

        ActionResult result = new ActionResult();
        SalesReturnApplyDO salesReturnApplyDO = new SalesReturnApplyDO();
        SaleIntentionVO saleIntentionVO = saleAddVO.getHeaderInfo();
        salesReturnApplyDO.setApplyNo(genDocumentService.getDocumentNo(BillDesc.ReturnApply));
        salesReturnApplyDO.setPurchaseOrgId(saleIntentionVO.getPurchaseOrgId());
        salesReturnApplyDO.setPurchaseOrgName(saleIntentionVO.getPurchaseOrgName());
        salesReturnApplyDO.setBuyerId(saleIntentionVO.getReceiverName());//收货人设为采购员
        salesReturnApplyDO.setSupplierOrgId(saleIntentionVO.getSupplierOrgId());
        salesReturnApplyDO.setSupplierOrgName(saleIntentionVO.getSupplierOrgName());
        salesReturnApplyDO.setCreateDate(new Date());
        salesReturnApplyDO.setUpdateDate(new Date());
        salesReturnApplyDO.setSaleNo(saleAddVO.getHeaderInfo().getSaleNo());
        salesReturnApplyDO.setId(applyId);
        salesReturnApplyDO.setRemark(remark);
        salesReturnApplyDO.setDept(deptName);
        salesReturnApplyDO.setCreateId(userId);
        salesReturnApplyDO.setCreateName(userName);
        salesReturnApplyDO.setSalesmanId(saleAddVO.getHeaderInfo().getCreatorId());
        salesReturnApplyDO.setSalesmanName(saleAddVO.getHeaderInfo().getCreateName());

        List<SaleIntentionDetailVO> saleIntentionDetailVOList = saleAddVO.getMaterialList();

        if (ListUtil.isNullOrEmpty(saleIntentionDetailVOList)) {
            result.setCode(ErrorCode.Success.getCode());
            return result;
        }
        List<SalesReturnApplyDetailDO> salesReturnApplyDetailDOList = new ArrayList<>();

        for (SaleIntentionDetailVO saleIntentionDetailVO : saleIntentionDetailVOList) {
            SalesReturnApplyDetailDO salesReturnApplyDetailDO = new SalesReturnApplyDetailDO();
            salesReturnApplyDetailDO.setApplyId(applyId);
            salesReturnApplyDetailDO.setSaleNo(saleAddVO.getHeaderInfo().getSaleNo());
            salesReturnApplyDetailDO.setMaterialsNo(saleIntentionDetailVO.getMaterialsNo());
            salesReturnApplyDetailDO.setMaterialsDes(saleIntentionDetailVO.getMaterialsDes());
            salesReturnApplyDetailDO.setUnit(saleIntentionDetailVO.getUnit());
            salesReturnApplyDetailDO.setApplyQty(saleIntentionDetailVO.getQty());
            salesReturnApplyDetailDO.setIsIn(0);
            salesReturnApplyDetailDO.setQty(saleIntentionDetailVO.getQty());
            salesReturnApplyDetailDO.setIsReturn(0);
            salesReturnApplyDetailDOList.add(salesReturnApplyDetailDO);
        }
        int ret = returnApplyMapper.insert(salesReturnApplyDO);

        if (0 >= ret) {
            result.setCode(ErrorCode.SalesReturnAddFail.getCode());
            return result;
        }
        ErrorCode errorCode = returnApplyDetailService.insert(salesReturnApplyDetailDOList);
        if (ErrorCode.Success != errorCode) {
            result.setCode(errorCode.getCode());
            return result;
        }
        result.setCode(ErrorCode.Success.getCode());
        result.setValue(salesReturnApplyDO.getApplyNo());
        return result;
    }


    /**
     * 销售意向单未出库，审核退货申请单时:<br>
     * 变更销售意向单状态为退货完成，如果存在发货单，变更发货单状态为退货完成<br>
     * 同时更改退货申请单状态为审核通过&退货完成<br>
     *
     * @param salesReturnApplyVO SalesReturnApplyVO
     * @return ErrorCode ErrorCode
     */
    @Transactional(rollbackFor = Exception.class)
    private ErrorCode saleIntentionReturnDone(SalesReturnApplyVO salesReturnApplyVO) throws Exception
    {
        String saleNo = salesReturnApplyVO.getSaleNo();
        //销售意向单退货完成状态
        saleIntentionService.updateReturnStatus(saleNo, SalesReturnConstants.DONE_RETURN);

        //发货通知单退货完成状态
        ErrorCode errorCode = deliveryNoteReturnDone(saleNo);
        if (ErrorCode.Success != errorCode)
        {
            throw new Exception("添加退货申请，修改发货单状态异常！");
        }
        //修改退货申请单为退货完成状态
        salesReturnApplyVO.setIsReturn(SalesReturnConstants.DONE_RETURN);//退货完成

        ErrorCode updateCode = updateApplyInfo(salesReturnApplyVO);
        if (ErrorCode.Success != updateCode)
        {
            return updateCode;
        }
        return ErrorCode.Success;
    }

    /**
     * 更改退货状态为退货中<br>
     * 销售意向单状态为退货中，退货申请单状态为退货中
     *
     * @param salesReturnApplyVO SalesReturnApplyVO
     * @return ErrorCode
     * @throws Exception Exception
     */
    @Transactional(rollbackFor = Exception.class)
    private ErrorCode saleIntentionReturnDoing(SalesReturnApplyVO salesReturnApplyVO) throws Exception
    {
        String saleNo = salesReturnApplyVO.getSaleNo();
        //销售意向单退货中状态
        saleIntentionService.updateReturnStatus(saleNo, SalesReturnConstants.DOING_RETURN);

        //修改退货申请单为退货中状态
        salesReturnApplyVO.setIsReturn(1);//退货中

        ErrorCode updateCode = updateApplyInfo(salesReturnApplyVO);
        if (ErrorCode.Success != updateCode)
        {
            return updateCode;
        }
        return ErrorCode.Success;
    }

    /**
     * 替换退货申请中的零件信息，用发货通知单中已出库的零件信息
     *
     * @param salesReturnApplyDetailDOList List<SalesReturnApplyDetailDO>
     * @param applyId                      String
     * @return ErrorCode
     * @throws Exception Exception
     */
    @Transactional(rollbackFor = Exception.class)
    private ErrorCode addApplyDetail(List<SalesReturnApplyDetailDO> salesReturnApplyDetailDOList, String applyId) throws Exception
    {
        returnApplyDetailService.deleteByApplyId(applyId);

        //合并零件集合中编码相同的零件
        salesReturnApplyDetailDOList = mergeApplyDetailDOList(salesReturnApplyDetailDOList);

        for (SalesReturnApplyDetailDO salesReturnApplyDetailDO : salesReturnApplyDetailDOList)
        {
            ErrorCode addCode = returnApplyDetailService.insertItem(salesReturnApplyDetailDO);
            if (ErrorCode.Success != addCode)
            {
                return addCode;
            }
            deliveryNoteMapper.updateReturnStatus(salesReturnApplyDetailDO.getDeliveryNo(), SalesReturnConstants.DOING_RETURN);
            deliveryNoteDetailMapper.updateReturnStatusById(salesReturnApplyDetailDO.getDeliveryDetailId(), SalesReturnConstants.DOING_RETURN);
        }
        return ErrorCode.Success;
    }

    /**
     * 合并零件集合中的数量
     *
     * @param applyDetailDOList List<SalesReturnApplyDetailDO>
     * @return List<SalesReturnApplyDetailDO>
     */
    private List<SalesReturnApplyDetailDO> mergeApplyDetailDOList(List<SalesReturnApplyDetailDO> applyDetailDOList)
    {
        List<SalesReturnApplyDetailDO> resultList = new ArrayList<>();
        for (SalesReturnApplyDetailDO detailDO : applyDetailDOList)
        {
            boolean flag = false;
            if (!ListUtil.isNullOrEmpty(resultList))
            {
                for (SalesReturnApplyDetailDO resultTemp : resultList)
                {
                    if (resultTemp.getMaterialsNo().equals(detailDO.getMaterialsNo()))
                    {
                        resultTemp.setApplyQty(resultTemp.getApplyQty().add(detailDO.getApplyQty()));
                        flag = true;
                    }
                }
            }
            if (flag == false)
            {
                resultList.add(detailDO);
            }
        }
        return resultList;
    }


    /**
     * 变更发货通知单状态为退货完成
     *
     * @param saleNo String
     * @return ErrorCode
     */
    private ErrorCode deliveryNoteReturnDone(String saleNo)
    {
        //修改发货单状态为退货完成
        DeliveryNoteVO deliveryNoteVO = new DeliveryNoteVO();
        deliveryNoteVO.setSaleNo(saleNo);

        //获取发货通知单信息
        List<DeliveryNoteDO> deliveryNoteDOs = deliveryNoteMapper.list(deliveryNoteVO);
        if (ListUtil.isNullOrEmpty(deliveryNoteDOs))
        {
            return ErrorCode.Success;
        }

        for (DeliveryNoteDO deliveryNoteDO : deliveryNoteDOs)
        {
            deliveryNoteService.updateReturnStatus(deliveryNoteDO.getId(), SalesReturnConstants.DONE_RETURN);
        }
        //更改出库事务单状态为退货
        warehouseDeliveryService.updateReturnStatus(deliveryNoteDOs,1);
        return ErrorCode.Success;
    }

    /**
     * 退货申请审核<br>
     * <li>审核通过，则生成退货入库单；</li>
     * <li>审核不通过，则录入审核拒绝原因</li>
     *
     * @param auditVO SalesReturnAuditVO
     * @return ErrorCode
     */
    @Transactional(rollbackFor = Exception.class)
    public ErrorCode audit(SalesReturnAuditVO auditVO) throws Exception
    {
        SalesReturnApplyVO applyVO = item(auditVO.getApplyId());

        if (null == applyVO)
        {
            return ErrorCode.IllegalArument;
        }

        if (applyVO.getStatus() != 0)
        {
            return ErrorCode.IllegalArument;
        }

        applyVO.setAuditDesc(auditVO.getAuditRemark());
        applyVO.setAuditId(auditVO.getAuditId());
        applyVO.setAuditName(auditVO.getAuditName());
        applyVO.setAuditDate(new Date());
        applyVO.setStatus(auditVO.getAuditStatus());//审核操作标识与审核状态是对应的

        //审核返回码
        ErrorCode auditCode;

        if (SalesReturnConstants.APPLY_STATUS_PASS.equals(auditVO.getAuditStatus()))
        {
            //审核通过
            auditCode = auditPass(applyVO);
        }
        else
        {
            //审核拒绝
            auditCode = auditFail(applyVO);
        }
        return auditCode;
    }

    /**
     * 审核退货申请单
     * @return ErrorCode
     * @throws Exception Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public ErrorCode auditReturnApply(SalesReturnApplyAddVO applyAddVO, String userId, String userName)throws Exception
    {
        SalesReturnApplyVO applyVO = item(applyAddVO.getId());

        if (null == applyVO)
        {
            return ErrorCode.IllegalArument;
        }

        if(applyVO.getStatus() == null || applyVO.getStatus() == 0){
            applyVO.setAuditId(userId);
            applyVO.setAuditName(userName);
            applyVO.setAuditDate(new Date());
            applyVO.setStatus(applyAddVO.getAuditStatus());//审核操作标识与审核状态是对应的
        }else{
            applyVO.setSecondAuditId(userId);
            applyVO.setSecondAuditName(userName);
            applyVO.setSecondAuditDate(new Date());
            applyVO.setStatus(applyAddVO.getAuditStatus()==1?3:4);
        }
        applyVO.setAuditDesc(applyAddVO.getAuditDesc());

        //审核返回码
        updateApplyInfo(applyVO);

        this.update(applyAddVO, 1);

//        applyVO = item(applyAddVO.getId());
//
//        if(applyAddVO.getAuditStatus() == 1 || applyAddVO.getAuditStatus() == 3){
//            List<SalesReturnApplyDetailVO> applyDetailVOList = applyVO.getReturnApplyDetailVOs();
//
//            for (SalesReturnApplyDetailVO record : applyDetailVOList)
//            {
//                //0未申请退货，1部分申请退货，2全部申请退货
//                int returnApplyStatus = 0;
//
//                SaleIntentionDetailDO saleIntentionDetailDO = saleIntentionDetailMapper.selectByNo(record.getSaleNo(), record.getMaterialsNo());
//
//                if (saleIntentionDetailDO.getAmountAfterAdjust().compareTo(record.getApplyQty()) > 0)
//                {
//                    //销售单零件数量大于退货申请数量，审核拒绝后销售单零件状态为部分申请退货
//                    returnApplyStatus = 1;
//                }
//                else if (saleIntentionDetailDO.getAmountAfterAdjust().compareTo(record.getApplyQty()) == 0)
//                {
//                    //销售单零件数量等于退货申请数量，审核拒绝后销售单零件状态为未申请退货
//                    returnApplyStatus = 0;
//                }
//                saleIntentionDetailMapper.updateByAutidFail(record.getApplyQty(), record.getSaleNo(), record.getMaterialsNo(), returnApplyStatus);
//            }
//
//            saleIntentionService.refreshSaleBillReturnStatus(applyVO.getSaleNo());
//        }

        return ErrorCode.Success;
    }

    /**
     * 审核拒绝，录入审核拒绝原因
     *
     * @param applyVO SalesReturnApplyVO
     * @return ErrorCode
     */
    @Transactional(rollbackFor = Exception.class)
    private ErrorCode auditFail(SalesReturnApplyVO applyVO) throws Exception
    {
        ErrorCode errorCode = updateApplyInfo(applyVO);

        if (ErrorCode.Success != errorCode)
        {
            throw new Exception("审核不通过，修改退货申请信息异常！");
        }

        saleIntentionMapper.updateApplyReturnStatus(applyVO.getSaleNo(), SalesReturnConstants.APPLY_FAIL);

        return errorCode;
    }

    /**
     * 修改退货申请信息
     *
     * @param applyVO SalesReturnApplyVO
     * @return ErrorCode
     */
    private ErrorCode updateApplyInfo(SalesReturnApplyVO applyVO)
    {
        SalesReturnApplyDO applyDO = getDO(applyVO);
        if (null == applyDO)
        {
            return ErrorCode.IllegalArument;
        }
        applyDO.setIsReturn(applyVO.getIsReturn());
        returnApplyMapper.update(applyDO);
        return ErrorCode.Success;
    }

    /**
     * 添加退货申请<br>
     * 判断销售意向单退货申请状态，如果是“已申请”或者“审核通过”，则无法提交申请
     *
     * @param applyAddVO SalesReturnApplyAddVO
     * @return ErrorCode
     */
    @Transactional(rollbackFor = Exception.class)
    public ActionResult add(SalesReturnApplyAddVO applyAddVO) throws Exception {
        //查询销售意向单
        SaleAddVO saleAddVO = saleIntentionService.selectByNo(applyAddVO.getSaleNo());
        if (null == saleAddVO || null == saleAddVO.getHeaderInfo()) {
            throw new Exception(ErrorCode.SalesReturnAddFail.getDesc());
        }

        if (!"1".equals(StringUtils.trim(saleAddVO.getHeaderInfo().getStatus()))) {
            throw new Exception(ErrorCode.SalesBillIsSave.getDesc());
        }

        //如果是审核中、审核通过状态，返回“已申请退货”
        if (null != saleAddVO.getHeaderInfo().getIsReturn() && 0 != saleAddVO.getHeaderInfo().getApplyReturn() && 3 != saleAddVO.getHeaderInfo().getApplyReturn()) {
            throw new Exception(ErrorCode.SalesIsApplyReturn.getDesc());
        }

        //销售意向单退货申请状态“申请中”
        saleIntentionMapper.updateApplyReturnStatus(applyAddVO.getSaleNo(), 1);

        ActionResult<String> textResult = fastGenClient.textGuid();
        if (textResult == null || textResult.getCode() != 0) {
            throw new Exception(ErrorCode.Failure.getDesc());
        }
        String applyId = textResult.getValue();

        return addBySaleIntention(saleAddVO, applyId, applyAddVO.getRemark(), applyAddVO.getDeptName(), applyAddVO.getUserId(), applyAddVO.getUserName());
    }

    /**
     * 添加退货申请<br>
     *
     * 判断销售意向单退货申请状态，如果是“已申请”或者“审核通过”，则无法提交申请
     *
     * @param applyAddVO SalesReturnApplyAddVO
     * @return ErrorCode
     */
    @Transactional(rollbackFor = Exception.class)
    public ErrorCode addApply(SalesReturnApplyAddVO applyAddVO) throws Exception
    {
        Integer returnStatus = 1;//1部分退货、2全部退货

        //查询销售意向单
        SaleAddVO saleAddVO = saleIntentionService.selectByNo(applyAddVO.getSaleNo());
        if (null == saleAddVO || null == saleAddVO.getHeaderInfo())
        {
            return ErrorCode.SalesReturnAddFail;
        }

        if("0".equals(saleAddVO.getHeaderInfo().getDeliverStatus()))
        {
            return ErrorCode.SaleBillNotOut;//未发货的销售单不可以退货
        }

        if (!"1".equals(saleAddVO.getHeaderInfo().getStatus().trim()))
        {
            return ErrorCode.SalesBillIsSave;
        }
//        //校验销售单状态是否已经全部申请退货
//        if (saleAddVO.getHeaderInfo().getApplyReturn() == 2)
//        {
//            return ErrorCode.SalesIsApplyReturn;
//        }

        //生成退货申请ID
        ActionResult<String> textResult = fastGenClient.textGuid();
        if (textResult == null || textResult.getCode() != 0)
        {
            return ErrorCode.Failure;
        }
        String applyId = textResult.getValue();

        List<SalesReturnApplyDetailVO> applyDetailVOS = applyAddVO.getReturnApplyDetailVOs();
        List<SaleIntentionDetailVO> materialList = saleAddVO.getMaterialList();

        Ref<Boolean> returnFlag = new Ref<>(true);//默认为全部申请退货

        List<SalesReturnApplyDetailDO> salesReturnApplyDetailDOList = packageApply(returnFlag, applyId, saleAddVO.getHeaderInfo().getSaleNo(), applyDetailVOS, materialList);

        //判断此次退货申请是否是全部退货
        if (returnFlag.get())
        {
            returnStatus = 2;
        }

        //.更改销售单状态为全部退货或者部分退货
        //销售意向单退货申请状态
        saleIntentionMapper.updateApplyReturnStatus(applyAddVO.getSaleNo(), returnStatus);

        SalesReturnApplyDO salesReturnApplyDO = new SalesReturnApplyDO();

        SaleIntentionVO saleIntentionVO = saleAddVO.getHeaderInfo();
        BeanUtils.copyProperties(applyAddVO, salesReturnApplyDO);
        salesReturnApplyDO.setApplyNo(genDocumentService.getDocumentNo(BillDesc.ReturnApply));
        salesReturnApplyDO.setPurchaseOrgId(saleIntentionVO.getPurchaseOrgId());
        salesReturnApplyDO.setPurchaseOrgName(saleIntentionVO.getPurchaseOrgName());
        salesReturnApplyDO.setBuyerId(saleIntentionVO.getReceiverName());//收货人设为采购员
        salesReturnApplyDO.setSupplierOrgId(saleIntentionVO.getSupplierOrgId());
        salesReturnApplyDO.setSupplierOrgName(saleIntentionVO.getSupplierOrgName());
        salesReturnApplyDO.setCreateDate(new Date());
        salesReturnApplyDO.setUpdateDate(new Date());
        salesReturnApplyDO.setSaleNo(saleAddVO.getHeaderInfo().getSaleNo());
        salesReturnApplyDO.setId(applyId);
        salesReturnApplyDO.setRemark(applyAddVO.getRemark());
        salesReturnApplyDO.setDept(applyAddVO.getDeptName());
        salesReturnApplyDO.setCreateId(applyAddVO.getUserId());
        salesReturnApplyDO.setCreateName(applyAddVO.getUserName());
        salesReturnApplyDO.setSalesmanId(saleAddVO.getHeaderInfo().getCreatorId());
        salesReturnApplyDO.setSalesmanName(saleAddVO.getHeaderInfo().getCreateName());
        int ret = returnApplyMapper.insert(salesReturnApplyDO);
        if (0 >= ret)
        {
            return ErrorCode.SalesReturnAddFail;
        }
        return returnApplyDetailService.insert(salesReturnApplyDetailDOList);
        //        return addBySaleIntention(saleAddVO, applyId, applyAddVO.getRemark(),applyAddVO.getDeptName(), applyAddVO.getUserId(), applyAddVO.getUserName());
    }

    /**
     *
     * @param applyAddVO
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public ErrorCode update(SalesReturnApplyAddVO applyAddVO, Integer type) throws Exception
    {
        List<SalesReturnApplyDetailVO> applyDetailVOS =     applyAddVO.getReturnApplyDetailVOs();
        SalesReturnApplyDO applyDO =   returnApplyMapper.item(applyAddVO.getId());

        if(applyAddVO.getAuditStatus() == null && (applyDO.getStatus() == 2 || applyDO.getStatus() == 4))
        {
            return ErrorCode.CannotEditAudited;
        }

        for (SalesReturnApplyDetailVO temp:applyDetailVOS)
        {
            SalesReturnApplyDetailDO applyDetailDO = returnApplyDetailMapper.itemByNo(temp.getMaterialsNo(), temp.getApplyId());
            SaleIntentionDetailDO saleIntentionDetailDO = saleIntentionDetailMapper.selectByNo(applyDetailDO.getSaleNo(), applyDetailDO.getMaterialsNo());

            BigDecimal totalAmount = saleIntentionDetailDO.getAmountAfterAdjust();//调整后采购数量
            BigDecimal returnYetAmout = saleIntentionDetailDO.getReturnApplyAmount()==null?new BigDecimal("0"):saleIntentionDetailDO.getReturnApplyAmount();//已退货数量
            BigDecimal thisReturnAmout = temp.getApplyQty();//修改后退货数量
            BigDecimal lastReturnAmount = applyDetailDO.getApplyQty();//上次退货数量

            BigDecimal tempAmount = returnYetAmout.subtract(lastReturnAmount).add(thisReturnAmout);

            if(totalAmount.compareTo(tempAmount)==0)
            {
                applyDetailDO.setIsReturn(2);//全部退货申请
                saleIntentionDetailDO.setIsReturn(2);
            }
            else if(totalAmount.compareTo(tempAmount)>0)
            {
              if(tempAmount.compareTo(BigDecimal.ZERO)==0)
              {
                  throw new Exception("退货数量不可以为0");
              }
                applyDetailDO.setIsReturn(1);//部分退货申请
                saleIntentionDetailDO.setIsReturn(1);
            }
            else  if(totalAmount.compareTo(tempAmount)<0)
            {
                throw new Exception("退货数量不能大于采购数量");
            }

            applyDetailDO.setApplyQty(temp.getApplyQty());
            applyDetailDO.setCheckOutNum(temp.getCheckOutNum());
            applyDetailDO.setPriceDiscount(temp.getPriceDiscount());
            applyDetailDO.setDiscount(temp.getDiscount());
            returnApplyDetailMapper.update(applyDetailDO);

            saleIntentionDetailDO.setReturnApplyAmount(tempAmount);

            saleIntentionDetailMapper.update(saleIntentionDetailDO);
        }
        applyDO.setRemark(applyAddVO.getRemark());
        applyDO.setReturnCategoryCode(applyAddVO.getReturnCategoryCode());
        applyDO.setReturnCategoryName(applyAddVO.getReturnCategoryName());
        applyDO.setReturnReasonCode(applyAddVO.getReturnReasonCode());
        applyDO.setReturnReasonName(applyAddVO.getReturnReasonName());
        applyDO.setPayConditionCode(applyAddVO.getPayConditionCode());
        applyDO.setPayConditionName(applyAddVO.getPayConditionName());
        if(type == null && (applyDO.getStatus() == 1 || applyDO.getStatus() == 3)){
            applyDO.setStatus(0);
        }
        returnApplyMapper.update(applyDO);
        saleIntentionService.refreshSaleBillReturnStatus(applyDO.getSaleNo());
        return ErrorCode.Success;
    }

    /**
     *
     * @param returnFlag
     * @param applyId
     * @param saleNo
     * @param applyList
     * @param materialList
     * @return
     * @throws Exception
     */
    private List<SalesReturnApplyDetailDO> packageApply(Ref<Boolean> returnFlag,String applyId, String  saleNo,List<SalesReturnApplyDetailVO> applyList, List<SaleIntentionDetailVO> materialList)throws Exception
    {
        List<SalesReturnApplyDetailDO> salesReturnApplyDetailDOList = new ArrayList<>();
        boolean tempFlag = true;
        for (SaleIntentionDetailVO material : materialList)
        {
            for (SalesReturnApplyDetailVO apply : applyList)
            {
                if (material.getId().equals(apply.getId()) || material.getMaterialsNo().equals(apply.getMaterialsNo()))
                {

                    SalesReturnApplyDetailDO salesReturnApplyDetailDO = new SalesReturnApplyDetailDO();

                    salesReturnApplyDetailDO.setApplyId(applyId);
                    salesReturnApplyDetailDO.setSaleNo(saleNo);
                    salesReturnApplyDetailDO.setMaterialsNo(material.getMaterialsNo());
                    salesReturnApplyDetailDO.setMaterialsDes(material.getMaterialsDes());
                    salesReturnApplyDetailDO.setUnit(material.getUnit());
                    salesReturnApplyDetailDO.setIsIn(0);
                    salesReturnApplyDetailDO.setQty(material.getAmountAfterAdjust());
                    salesReturnApplyDetailDO.setApplyQty(apply.getApplyQty());
                    salesReturnApplyDetailDO.setPriceSchemeId(apply.getPriceSchemeId());
                    salesReturnApplyDetailDO.setPriceSchemeName(apply.getPriceSchemeName());
                    salesReturnApplyDetailDO.setPrice(apply.getPrice());
                    salesReturnApplyDetailDO.setDiscount(apply.getDiscount());
                    salesReturnApplyDetailDO.setPriceDiscount(apply.getPriceDiscount());

                    BigDecimal applyAmount = apply.getApplyQty();//本次申请退货数量
                    BigDecimal returnApplyYet = material.getReturnApplyAmount()==null?new BigDecimal("0"):material.getReturnApplyAmount();//已申请退货数量
                    BigDecimal totalAmount = material.getAmountAfterAdjust();//调整后采购数量

                    BigDecimal tempAmount = applyAmount.add(returnApplyYet);

                    if (tempAmount.compareTo(totalAmount) > 0)//退货申请数量和采购数量比较
                    {
                        throw new Exception("退货数量不可大于采购数量！");
                    }
                    else if (tempAmount.compareTo(totalAmount) == 0)
                    {
                        salesReturnApplyDetailDO.setIsReturn(2);//全部退货
                    }
                    else
                    {
                        tempFlag = false;//整个单据将不可能全部退货
                        salesReturnApplyDetailDO.setIsReturn(1);//部分退货
                    }
                    salesReturnApplyDetailDOList.add(salesReturnApplyDetailDO);
                }
            }
        }
        if(materialList.size()==applyList.size()&&tempFlag)//申请退货零件数和销售单零件数相同，且零件申请的退货数量等于销售单数量
        {
            returnFlag.set(true);
        }
        else
        {
            returnFlag.set(false);
        }
        return salesReturnApplyDetailDOList;
    }



    /**
     * 退货入库单入库完成，更新退货申请单、销售意向单、发货通知单
     *
     * @param returnInDO SalesReturnInDO
     * @return ErrorCode
     */
    public ErrorCode salesReturnInSuccess(SalesReturnInDO returnInDO, String materialNo, BigDecimal realAmount)throws Exception
    {
        String applyId = returnInDO.getApplyId();
        SalesReturnApplyDO returnApplyDO = returnApplyMapper.item(applyId);
        if(returnApplyDO == null){
            throw new Exception("更新退货神请入库状态失败");
        }
        SalesReturnApplyDetailDO applyDetailDO = returnApplyDetailMapper.itemByNo(materialNo, applyId);
        if(applyDetailDO == null){
            throw new Exception("更新退货神请入库状态失败");
        }
        if(applyDetailDO.getInQty() == null){
            applyDetailDO.setInQty(BigDecimal.ZERO);
        }
        applyDetailDO.setInQty(applyDetailDO.getInQty().add(realAmount));
        if(applyDetailDO.getApplyQty().compareTo(applyDetailDO.getInQty()) < 0){
            throw new Exception("实际入库数量不能大于退货申请数量");
        }else if(applyDetailDO.getApplyQty().compareTo(applyDetailDO.getInQty()) == 0){
            applyDetailDO.setIsIn(2);
        }else{
            applyDetailDO.setIsIn(1);
        }
        boolean success = returnApplyDetailMapper.update(applyDetailDO)>0;
        if(!success){
            throw new Exception("更新退货神请入库状态失败");
        }

        Integer isIn = 2;
        List<SalesReturnApplyDetailDO> applyDetailDOList = returnApplyDetailMapper.list(applyId);
        for(SalesReturnApplyDetailDO detailDO : applyDetailDOList){
            if(detailDO.getIsIn() != 2){
                isIn = 1;
            }
        }
        SalesReturnApplyDO returnApply = new SalesReturnApplyDO();
        returnApply.setId(applyId);
        returnApply.setIsIn(isIn);
        success = returnApplyMapper.update(returnApply)>0;
        if(!success){
            throw new Exception("更新退货神请入库状态失败");
        }
        return ErrorCode.Success;
    }

    /**
     * 强制完成退货入库单，同时更改“退货申请”、“销售意向单”、“发货通知单”状态为退货完成
     * @param returnInDO SalesReturnInDO
     * @return ErrorCode
     */
    public  ErrorCode  manualFinishReturnIn(SalesReturnInDO returnInDO)
    {
        SalesReturnApplyDO returnApplyDO = returnApplyMapper.item(returnInDO.getApplyId());

        if (null == returnApplyDO)
        {
            return ErrorCode.IllegalArument;
        }

        SalesReturnApplyDO applyDO  = new SalesReturnApplyDO();
        applyDO.setId(returnApplyDO.getId());
        applyDO.setIsReturn(2);
        returnApplyMapper.update(applyDO);//退货申请退货完成

        //修改退货状态为退货完成
        saleIntentionMapper.updateReturnStatus(returnApplyDO.getSaleNo(), SalesReturnConstants.DONE_RETURN);
        deliveryNoteService.updateReturnStatusBySaleNo(returnApplyDO.getSaleNo(), SalesReturnConstants.DONE_RETURN);
        return ErrorCode.Success;
    }

    /**
     * 获取退货申请业务对象
     *
     * @param applyAddVO SalesReturnApplyAddVO
     * @return SalesReturnApplyVO
     */
    private SalesReturnApplyVO getSalesReturnApplyVO(SalesReturnApplyAddVO applyAddVO)
    {
        SalesReturnApplyVO salesReturnApplyVO = new SalesReturnApplyVO();
        List<SalesReturnApplyDetailVO> salesReturnApplyDetailVOs = new ArrayList<>();

        SaleAddVO saleAddVO = saleIntentionService.selectByNo(applyAddVO.getSaleNo());
        if (null == saleAddVO || null == saleAddVO.getHeaderInfo())
        {
            return null;
        }

        salesReturnApplyVO.setSupplierOrgId(saleAddVO.getHeaderInfo().getSupplierOrgId());
        salesReturnApplyVO.setSupplierOrgName(saleAddVO.getHeaderInfo().getSupplierOrgName());
        salesReturnApplyVO.setPurchaseOrgId(saleAddVO.getHeaderInfo().getPurchaseOrgId());
        salesReturnApplyVO.setPurchaseOrgName(saleAddVO.getHeaderInfo().getPurchaseOrgName());
        salesReturnApplyVO.setSaleNo(saleAddVO.getHeaderInfo().getSaleNo());

        //退货申请零件信息（主要取零件数量）
        List<SalesReturnApplyDetailVO> applyDetailVOs = applyAddVO.getReturnApplyDetailVOs();

        if (!ListUtil.isNullOrEmpty(applyDetailVOs))
        {
            for (SalesReturnApplyDetailVO detailVO : applyDetailVOs)
            {
                SaleIntentionDetailDO detailDO = saleIntentionDetailMapper.selectByNo(applyAddVO.getSaleNo(), detailVO.getMaterialsNo());
                SalesReturnApplyDetailVO applyDetailVO = new SalesReturnApplyDetailVO();
                applyDetailVO.setMaterialsNo(detailDO.getMaterialsNo());
                applyDetailVO.setMaterialsDes(detailDO.getMaterialsDes());
                applyDetailVO.setMaterialsType(detailDO.getMaterialsDes());
                applyDetailVO.setUnit(detailDO.getUnit());
                applyDetailVO.setReturnQty(detailVO.getReturnQty());

                salesReturnApplyDetailVOs.add(applyDetailVO);
            }
        }

        salesReturnApplyVO.setReturnApplyDetailVOs(salesReturnApplyDetailVOs);
        return salesReturnApplyVO;
    }

    /**
     * 导出所选申请单单
     *
     * @param ids List 申请单ID集合
     * @throws Exception Exception
     */
    public void export(List<String> ids) throws Exception
    {
        List<SalesReturnApplyExportVO> exportVOList = new ArrayList<>();
        List<SalesReturnApplyVO> applyVOs = new ArrayList<>();
        for (String id : ids)
        {
            SalesReturnApplyVO applyVO = item(id);

            if (null == applyVO)
            {
                continue;
            }
            applyVOs.add(applyVO);

            //根据退货入库，查询对应详情信息(退货申请单号)
            List<SalesReturnApplyDetailVO> detailVOList = returnApplyDetailService.itemsById(applyVO.getApplyNo());
            if (ListUtil.isNullOrEmpty(detailVOList))
            {
                exportVOList.add(getExportVO(applyVO, null));
                continue;
            }

            for (SalesReturnApplyDetailVO detailVO : detailVOList)
            {
                //封装导出所需的VO对象
                exportVOList.add(getExportVO(applyVO, detailVO));
            }
        }
        invokeExport(applyVOs);
    }

    /**
     * 修改退货数量后更改退货申请单状态<br>
     * if （申请数量=退货数量 && 部分退货状态）更改退货状态为“全部退货”<br>
     * else if（申请数量=退货数量 && 全部退货状态） 更改退货状态为“部分退货“
     *
     * @param applyId String
     * @return ErrorCode
     * @throws Exception 
     */
    public ErrorCode updateReturnStatus(String applyId) throws Exception
    {
        SalesReturnApplyVO returnApplyVO = item(applyId);
        boolean returnFlag = true;//默认全部退货
        if (null == returnApplyVO)
        {
            return ErrorCode.Success;
        }
        List<SalesReturnApplyDetailVO> applyDetailVOs = returnApplyVO.getReturnApplyDetailVOs();
        if (ListUtil.isNullOrEmpty(applyDetailVOs))
        {
            return ErrorCode.Success;
        }

        //判断零件退货数量是否存在“部分退货”情况
        for (SalesReturnApplyDetailVO temp : applyDetailVOs)
        {
            if (!temp.getReturnQty().equals(temp.getApplyQty()))
            {
                returnFlag = false;
                break;
            }
        }
        //当前退货状态
        Integer retenStatus = returnApplyVO.getIsReturn();

        if (returnFlag && retenStatus.equals(SalesReturnConstants.DOING_RETURN))
        {
            SalesReturnApplyDO applyDO = new SalesReturnApplyDO();
            applyDO.setId(returnApplyVO.getId());
            applyDO.setIsReturn(SalesReturnConstants.DONE_RETURN);
            returnApplyMapper.update(applyDO);
        }
        else if (!returnFlag && retenStatus.equals(SalesReturnConstants.DONE_RETURN))
        {
            SalesReturnApplyDO applyDO = new SalesReturnApplyDO();
            applyDO.setId(returnApplyVO.getId());
            applyDO.setIsReturn(SalesReturnConstants.DOING_RETURN);
            returnApplyMapper.update(applyDO);
        }
        return ErrorCode.Success;
    }

    /**
     * 导出（当前企业）全部申请单集合
     *
     * @param condition SalesReturnInVO
     * @throws Exception Exception
     */
    public void exportAll(SalesReturnApplyVO condition) throws Exception
    {
        SearchCommonVO<SalesReturnApplyVO> returnInVOSearchCommonVO = new SearchCommonVO<>();
        returnInVOSearchCommonVO.setFilters(condition);
        returnInVOSearchCommonVO.setPageNum(0);
        returnInVOSearchCommonVO.setPageSize(0);

        //查询所有记录
        PageCommonVO pageCommonVO = list(returnInVOSearchCommonVO);
        List<SalesReturnApplyVO> returnApplyVOs = pageCommonVO.getPageInfoList();

        List<SalesReturnApplyExportVO> exportVOList = new ArrayList<>();

        //循环退货入库信息，查询出对应的零件信息
        for (SalesReturnApplyVO temp : returnApplyVOs)
        {
            //根据退货入库，查询对应详情信息(退货申请单号)
            List<SalesReturnApplyDetailVO> detailVOList = returnApplyDetailService.itemsById(temp.getApplyNo());
            if (ListUtil.isNullOrEmpty(detailVOList))
            {
                exportVOList.add(getExportVO(temp, null));
                continue;
            }

            for (SalesReturnApplyDetailVO detailVO : detailVOList)
            {
                //封装导出所需的VO对象
                exportVOList.add(getExportVO(temp, detailVO));
            }
        }
        invokeExport(returnApplyVOs);
    }

    /**
     * 导出退货入库单
     *
     * @param exportVOs List
     * @throws Exception Exception
     */
    private void invokeExport( List<SalesReturnApplyVO> exportVOs) throws Exception
    {
        String title = "退货申请单导出";
        String[] rowsName = new String[]{"序号", "退货申请单号","销售意向单号", "采购公司", "备件公司","申请时间", "退货状态", "审核人","制单部门", "审核时间", "审核状态", "审核意见", "备注"};
        List<Object[]> dataList = new ArrayList<Object[]>();
        Object[] objs = null;

        if (ListUtil.isNullOrEmpty(exportVOs))
        {
            ExportUtil exportUtil = new ExportUtil(title, rowsName, dataList);
            exportUtil.export(response);
            return;
        }
        for (int i = 0; i < exportVOs.size(); i++)
        {
            SalesReturnApplyVO e = exportVOs.get(i);
            objs = new Object[rowsName.length];
            objs[0] = i + 1;
            objs[1] = e.getApplyNo();
            objs[2] = e.getSaleNo();
            objs[3] = e.getPurchaseOrgName();
            objs[4] = e.getSupplierOrgName();
            objs[5] = DateUtil.formatDateTime(e.getCreateDate());
            objs[6] = e.getIsReturnDesc();
            objs[7] = e.getAuditName();
            objs[8] = e.getDept();
            objs[9] = e.getAuditDate()==null? "": DateUtil.formatDateTime(e.getAuditDate());
            objs[10] = e.getStatusDesc();
            objs[11] = e.getAuditDesc();
            objs[12] = e.getRemark();
            dataList.add(objs);
        }
        ExportUtil exportUtil = new ExportUtil(title, rowsName, dataList);
        exportUtil.export(response);
    }

    public SalesReturnApplyExportVO getExportVO(SalesReturnApplyVO applyVO, SalesReturnApplyDetailVO applyDetailVO)
    {
        SalesReturnApplyExportVO exportVO = new SalesReturnApplyExportVO();
        if (null != applyVO)
        {
            exportVO.setApplyNo(applyVO.getApplyNo());
            exportVO.setPurchaseOrgName(applyVO.getPurchaseOrgName());
            exportVO.setCreateDate(applyVO.getCreateDate());
            exportVO.setIsReturn(applyVO.getIsReturnDesc());
            exportVO.setAuditName(applyVO.getAuditName());
            exportVO.setAuditDate(applyVO.getAuditDate());
            exportVO.setStatus(applyVO.getStatusDesc());
            exportVO.setAuditDesc(applyVO.getAuditDesc());
        }
        if (null != applyDetailVO)
        {
            //加入详情中单价的显示 addby huhuawei/2018-9-14
            exportVO.setPrice(applyDetailVO.getPrice());
            exportVO.setPriceDiscount(applyDetailVO.getPriceDiscount());
            exportVO.setDiscount(applyDetailVO.getDiscount());

            exportVO.setMaterialsNo(applyDetailVO.getMaterialsNo());
            exportVO.setMaterialsType(applyDetailVO.getMaterialsType());
            exportVO.setMaterialsDes(applyDetailVO.getMaterialsDes());
            exportVO.setUnit(applyDetailVO.getUnit());
            exportVO.setQty(applyDetailVO.getQty());
            exportVO.setApplyQty(applyDetailVO.getApplyQty());
            exportVO.setReturnQty(applyDetailVO.getReturnQty());
            exportVO.setInQty(applyDetailVO.getInQty());
            exportVO.setMaterialsIsIn(applyDetailVO.getIsInDesc());
            exportVO.setMaterialsIsReturn(applyDetailVO.getIsReturnDesc());
        }

        return exportVO;
    }


    /**
     * @param beanDO SalesReturnApplyDO
     * @return SalesReturnApplyVO
     */
    private SalesReturnApplyVO getVO(SalesReturnApplyDO beanDO)
    {
        if (null == beanDO)
        {
            return null;
        }
        SalesReturnApplyVO beanVO = new SalesReturnApplyVO();

        BeanUtils.copyProperties(beanDO, beanVO);


        //0待审核，1审核拒绝，2审核通过
        switch (beanDO.getStatus()){
            case 0 :
                beanVO.setStatusDesc("待审核");
                break;
            case 1 :
                beanVO.setStatusDesc("第一步审核拒绝");
                break;
            case 2 :
                beanVO.setStatusDesc("第一步审核通过");
                break;
            case 3 :
                beanVO.setStatusDesc("第二步审核拒绝");
                break;
            case 4 :
                beanVO.setStatusDesc("第二步审核通过");
                break;
        }

        //是否入库（0未入库，1入库中，2入库完成）
        if (1 == beanDO.getIsIn())
        {
            beanVO.setIsInDesc("入库中");
        }
        else if (2 == beanDO.getIsIn())
        {
            beanVO.setIsInDesc("入库完成");
        }
        else
        {
            beanVO.setIsInDesc("未入库");
        }

        //是否退货，退货入库单是否生成（0未退货，1退货中，2退货完成）
        if (1 == beanDO.getIsReturn())
        {
            beanVO.setIsReturnDesc("部分退货");
        }
        else if (2 == beanDO.getIsReturn())
        {
            beanVO.setIsReturnDesc("全部退货");
        }
        else
        {
            beanVO.setIsReturnDesc("未退货");
        }
        return beanVO;
    }

    /**
     * @param beanVO SalesReturnApplyVO
     * @return SalesReturnApplyDO
     */
    private SalesReturnApplyDO getDO(SalesReturnApplyVO beanVO)
    {
        if (null == beanVO)
        {
            return null;
        }
        SalesReturnApplyDO beanDO = new SalesReturnApplyDO();

        BeanUtils.copyProperties(beanVO, beanDO);
        return beanDO;
    }

    /**
     * @Author: WangKe
     * @Description: 选择零件新增退货申请
     * @Date: 2018/7/6 0006
     */
    @Transactional(rollbackFor = Exception.class)
    public ErrorCode manulAdd(SalesReturnApplyAddVO applyAddVO, String orgId)throws Exception{
        if(applyAddVO == null || ListUtil.isNullOrEmpty(applyAddVO.getReturnApplyDetailVOs())){
            return ErrorCode.IllegalArument;
        }
        CompanyInfoDO companyInfoDO = companyInfoMapper.item(orgId);
        if(companyInfoDO == null){
            return ErrorCode.IllegalArument;
        }
        ActionResult<String> textResult = fastGenClient.textGuid();
        if (textResult == null || textResult.getCode() != 0)
        {
            return ErrorCode.Failure;
        }
        String applyId = textResult.getValue();
        SalesReturnApplyDO returnApplyDO = new SalesReturnApplyDO();
        BeanUtils.copyProperties(applyAddVO, returnApplyDO);
        returnApplyDO.setId(applyId);
        returnApplyDO.setApplyNo(genDocumentService.getDocumentNo(BillDesc.ReturnApply));
        returnApplyDO.setSupplierOrgId(orgId);
        returnApplyDO.setSupplierOrgName(companyInfoDO.getCompanyName());
        returnApplyDO.setCreateDate(new Date());
        returnApplyDO.setUpdateDate(returnApplyDO.getCreateDate());
        returnApplyDO.setIsIn(0);
        returnApplyDO.setIsReturn(0);
        returnApplyDO.setDept(applyAddVO.getDeptName());
        returnApplyDO.setCreateId(applyAddVO.getUserId());
        returnApplyDO.setCreateName(applyAddVO.getUserName());
        if(companyInfoDO.getIsReturnAudit() == 1){
            returnApplyDO.setStatus(0);
        }else{
            returnApplyDO.setStatus(4);
        }
        returnApplyMapper.insert(returnApplyDO);

        SalesReturnApplyDetailDO applyDetailDO = new SalesReturnApplyDetailDO();
        for(SalesReturnApplyDetailVO detailVOs : applyAddVO.getReturnApplyDetailVOs()){
            BeanUtils.copyProperties(detailVOs, applyDetailDO);
            applyDetailDO.setId(fastGenClient.textGuid().getValue());
            applyDetailDO.setApplyId(applyId);
            applyDetailDO.setQty(null);
            returnApplyDetailMapper.insert(applyDetailDO);
        }
        return ErrorCode.Success;
    }

    /**
     * @Author: WangKe
     * @Description: 选择零件新增的退货申请更新
     * @Date: 2018/7/6 0006
     */
    @Transactional(rollbackFor = Exception.class)
    public ErrorCode manulUpdate(SalesReturnApplyAddVO applyAddVO)throws Exception{
        if(applyAddVO == null || ListUtil.isNullOrEmpty(applyAddVO.getReturnApplyDetailVOs())){
            return ErrorCode.IllegalArument;
        }
        SalesReturnApplyDO returnApplyDO = new SalesReturnApplyDO();
        BeanUtils.copyProperties(applyAddVO, returnApplyDO);
        returnApplyDO.setStatus(0);
        returnApplyDO.setUpdateDate(new Date());
        returnApplyMapper.update(returnApplyDO);

        returnApplyDetailMapper.deleteByApply(returnApplyDO.getId());
        SalesReturnApplyDetailDO applyDetailDO = new SalesReturnApplyDetailDO();
        for(SalesReturnApplyDetailVO detailVOs : applyAddVO.getReturnApplyDetailVOs()){
            BeanUtils.copyProperties(detailVOs, applyDetailDO);
            applyDetailDO.setId(fastGenClient.textGuid().getValue());
            applyDetailDO.setApplyId(returnApplyDO.getId());
            applyDetailDO.setQty(null);
            returnApplyDetailMapper.insert(applyDetailDO);
        }
        return ErrorCode.Success;
    }

    @Transactional(rollbackFor = Exception.class)
    public ErrorCode manulAuditReturnApply(SalesReturnApplyAddVO applyAddVO, String userId, String userName)throws Exception{
        if(applyAddVO == null || ListUtil.isNullOrEmpty(applyAddVO.getReturnApplyDetailVOs())){
            return ErrorCode.IllegalArument;
        }
        SalesReturnApplyDO returnApplyDO = new SalesReturnApplyDO();
        BeanUtils.copyProperties(applyAddVO, returnApplyDO);
        returnApplyDO.setUpdateDate(new Date());
        if(applyAddVO.getStatus() == null || applyAddVO.getStatus() == 0){
            returnApplyDO.setAuditId(userId);
            returnApplyDO.setAuditName(userName);
            returnApplyDO.setAuditDate(new Date());

            returnApplyDO.setStatus(applyAddVO.getAuditStatus());//审核操作标识与审核状态是对应的
        }else{
            returnApplyDO.setSecondAuditId(userId);
            returnApplyDO.setSecondAuditName(userName);
            returnApplyDO.setSecondAuditDate(new Date());
            returnApplyDO.setStatus(applyAddVO.getAuditStatus()==1?3:4);
        }
        returnApplyDO.setAuditDesc(applyAddVO.getAuditDesc());
        returnApplyMapper.update(returnApplyDO);

        returnApplyDetailMapper.deleteByApply(returnApplyDO.getId());
        SalesReturnApplyDetailDO applyDetailDO = new SalesReturnApplyDetailDO();
        for(SalesReturnApplyDetailVO detailVOs : applyAddVO.getReturnApplyDetailVOs()){
            BeanUtils.copyProperties(detailVOs, applyDetailDO);
            applyDetailDO.setId(fastGenClient.textGuid().getValue());
            applyDetailDO.setApplyId(returnApplyDO.getId());
            applyDetailDO.setQty(null);
            returnApplyDetailMapper.insert(applyDetailDO);
        }

        return ErrorCode.Success;
    }

    public FunctionResult importExcel(InputStream in, String dealerOrgId, String orgId) throws Exception{
        FunctionResult result=new FunctionResult();
        HSSFWorkbook wb=new HSSFWorkbook(in);
        HSSFSheet sheet=wb.getSheetAt(0);

        int totalRow=sheet.getLastRowNum();
        if(totalRow<2){
            result.setCode(ErrorCode.IllegalArument);
            result.setValue("导入模板不正确");
            return result;
        }
        int totalCell=sheet.getRow(1).getLastCellNum();
        if(totalCell!=5){
            result.setCode(ErrorCode.IllegalArument);
            result.setValue("导入模板不正确");
            return result;
        }
        List<SalesReturnApplyDetailVO> detailVOList=new ArrayList<>();
        List<SalesReturnApplyDetailVO> errorDetailVOList=new ArrayList<>();
        for (int i=2;i<=totalRow;i++){
            HSSFRow curRow=sheet.getRow(i);
            SalesReturnApplyDetailVO detailVO = new SalesReturnApplyDetailVO();
            if(curRow==null){
                continue;
            }
            String materialsNo = getCellValue(curRow, 1);//零件编号
            String price = getCellValue(curRow, 3);
            String qty = getCellValue(curRow, 4);
            if(StringUtil.isNullOrEmpty(materialsNo)
                    && StringUtil.isNullOrEmpty(qty) && StringUtil.isNullOrEmpty(price)){
                continue;
            }
            if(StringUtil.isNullOrEmpty(materialsNo)){
                detailVO.setErrorRow(i+1);
                detailVO.setRemark("零件编码不能为空");
                errorDetailVOList.add(detailVO);
                continue;
            }
            if(StringUtil.isNullOrEmpty(qty)){
                detailVO.setErrorRow(i+1);
                detailVO.setRemark("退货数量不能为空");
                errorDetailVOList.add(detailVO);
                continue;
            }
            if(!isInteger(qty) || "0".equals(qty)){
                detailVO.setErrorRow(i+1);
                detailVO.setRemark("退货数量格式不正确");
                errorDetailVOList.add(detailVO);
                continue;
            }
            if(new BigDecimal(qty).compareTo(BigDecimal.valueOf(99999999.99)) > 0){
                detailVO.setErrorRow(i+1);
                detailVO.setRemark("退货数量过大");
                errorDetailVOList.add(detailVO);
                continue;
            }
            if(StringUtil.isNullOrEmpty(price)){
                detailVO.setErrorRow(i+1);
                detailVO.setRemark("价格不能为空");
                errorDetailVOList.add(detailVO);
                continue;
            }
            if(!isInteger(price) || "0".equals(price)){
                detailVO.setErrorRow(i+1);
                detailVO.setRemark("价格格式不正确");
                errorDetailVOList.add(detailVO);
                continue;
            }
            if(new BigDecimal(price).compareTo(BigDecimal.valueOf(999999999)) > 0){
                detailVO.setErrorRow(i+1);
                detailVO.setRemark("价格过大");
                errorDetailVOList.add(detailVO);
                continue;
            }
            MaterialsVO materialsVO=materialsService.itemByNo(materialsNo, orgId);
            if(materialsVO==null){
                detailVO.setErrorRow(i+1);
                detailVO.setRemark("零件不存在");
                errorDetailVOList.add(detailVO);
                continue;
            }
            detailVO.setApplyQty(new BigDecimal(qty));
            detailVO.setPrice(new BigDecimal(price));
            detailVO.setMaterialsNo(materialsVO.getMaterialsNo());
            detailVO.setMaterialsDes(materialsVO.getMaterialsDes());
            detailVO.setMaterialsType(materialsVO.getMaterialsType());
            detailVO.setUnit(materialsVO.getUnit());
            detailVO.setMarketingActivityPriceVOList(marketingActivityService.activityPriceList(dealerOrgId, orgId, detailVO.getMaterialsNo()));
            detailVOList.add(detailVO);
        }

        if(ListUtil.isNullOrEmpty(errorDetailVOList)){
            result.setValue(ImportUtil.deRepeat(detailVOList,"MaterialsNo","ApplyQty",null,null));
            result.setCode(ErrorCode.Success);
        }else{
            result.setValue(errorDetailVOList);
            result.setCode(ErrorCode.IllegalArument);
        }
        return result;
    }

    private boolean isInteger(String str) {
        if (null == str || "".equals(str)) {
            return false;
        }
        try {
            BigDecimal decimal = new BigDecimal(str);
        }catch (Exception e){
            return false;
        }
        return true;
    }

    private String getCellValue(HSSFRow curRow, int i){
        String value = "";
        if(curRow.getCell(i) != null){
            curRow.getCell(i).setCellType(CellType.STRING);
            value = curRow.getCell(i).getStringCellValue();
        }
        return value;
    }

    public void download() throws Exception{
        FileUtil.downLoadFile(response, filePath, templateExcelFileName);
    }

}
